home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / elv18src.zip / ref.c < prev    next >
C/C++ Source or Header  |  1994-01-17  |  13KB  |  579 lines

  1. /* ref2.c */
  2.  
  3. /* This is a totally rewritten version of ref.  This version looks for the
  4.  * desired function name in the "tags" file, and then reads the header out
  5.  * from the source file.  There is no longer any need for a "refs" file.
  6.  *
  7.  * Usage:    ref [-t] [-x] [-f file] [-c class] tag
  8.  * Options:    -t       output tag info, not the description
  9.  *        -x         require exact match
  10.  *        -f file       default filename for static functions
  11.  *        -c class   default class names for class functions
  12.  */
  13. #ifdef __STDC__
  14. # include <string.h>
  15. # include <stdlib.h>
  16. #endif
  17.  
  18. #include <stdio.h>
  19. #include "config.h"
  20.  
  21. extern char    *cktagdir P_((char *, char *));
  22. extern int    getline P_((char *, int, FILE *));
  23. extern int    lookup P_((char *, char *));
  24. extern int    find P_((char *));
  25. extern void    usage P_((void));
  26. extern int    countcolons P_((char *));
  27. extern void    main P_((int, char **));
  28.  
  29.  
  30. /* This is the default path that is searched for tags */
  31. #if OSK
  32. # define DEFTAGPATH ".:/dd/defs:/dd/defs/sys:/dd/usr/src/lib:../lib:/dd/usr/lib"
  33. #else
  34. # if ANY_UNIX
  35. #  define DEFTAGPATH ".:/usr/include:/usr/include/sys:/usr/src/lib:../lib:/usr/local/lib"
  36. # else
  37. #  if MSDOS || TOS || OS2
  38. #   define DEFTAGPATH ".;C:\\include;C:\\include\\sys;C:\\lib;..\\lib"
  39. #   define SEP ';'
  40. #  else
  41. #   if AMIGA
  42. #    define DEFTAGPATH ".;Include:;Include:sys"
  43. #    define SEP ';'
  44. #   else /* any other OS */
  45. #    define DEFTAGPATH "."
  46. #   endif
  47. #  endif
  48. # endif
  49. #endif
  50.  
  51. #ifndef SEP
  52. # define SEP ':'
  53. #endif
  54.  
  55.  
  56. /* These variables reflect the command-line options given by the user. */
  57. int    taginfo;    /* boolean: give only the tag info? (not header?) */
  58. int    exact;        /* boolean: require exact match? */
  59. char    *def_file;    /* default filename for static functions */
  60. char    *def_class;    /* default classname for class members */
  61. int    colons;        /* #colons in tag: 0=normal, 1=static, 2=member */
  62.  
  63. /* This function checks for a tag in the "tags" file of given directory.
  64.  * If the tag is found, then it returns a pointer to a static buffer which
  65.  * contains the filename, a tab character, and a linespec for finding the
  66.  * the tag.  If the tag is not found in the "tags" file, or if the "tags"
  67.  * file cannot be opened or doesn't exist, then this function returns NULL.
  68.  */
  69. char *cktagdir(tag, dir)
  70.     char    *tag;    /* name of the tag to look for */
  71.     char    *dir;    /* name of the directory to check */
  72. {
  73.     char    buf[BLKSIZE];
  74.     static char found[BLKSIZE];
  75.     FILE    *tfile;
  76.     int    len;
  77.     char    *scan;
  78.  
  79. #if AMIGA
  80.     if (dir[strlen(dir) - 1] == COLON)
  81.         sprintf(buf, "%s%s", dir, TAGS);   /* no slash after colon. */
  82.     else
  83. #endif
  84.     /* construct the name of the "tags" file in this directory */
  85.     sprintf(buf, "%s%c%s", dir, SLASH, TAGS);
  86.  
  87.     /* Try to open the tags file.  Return NULL if can't open */
  88. #if AMIGA
  89.     if (buf[0] == '.' && buf[1] == SLASH)
  90.         tfile = fopen(&buf[2], "r");
  91.     else
  92. #endif
  93.     tfile = fopen(buf, "r");
  94.     if (!tfile)
  95.     {
  96.         return (char *)0;
  97.     }
  98.  
  99.     /* compute the length of the tagname once */
  100.     len = strlen(tag);
  101.  
  102.     /* read lines until we get the one for this tag */
  103.     found[0] = '\0';
  104.     while (fgets(buf, sizeof buf, tfile))
  105.     {
  106.         /* is this the one we want? */
  107.         if (!strncmp(buf, tag, len) && buf[len] == '\t')
  108.         {
  109.             /* we've found a match -- remember it */
  110.             strcpy(found, buf);
  111.  
  112.             /* if there is no default file, or this match is in
  113.              * the default file, then we've definitely found the
  114.              * one we want.  Break out of the loop now.
  115.              */
  116.             if (!def_file || !strncmp(&buf[len + 1], def_file, strlen(def_file)))
  117.             {
  118.                 break;
  119.             }
  120.         }
  121.  
  122.         /* does it maybe match the stuff after the colons? */
  123.         if (!exact)
  124.         {
  125.             scan = strchr(buf, '\t');
  126.             if (scan
  127.              && (int)(scan - buf) > len
  128.              && scan[-len - 1] == ':'
  129.              && !strncmp(tag, scan - len, len))
  130.             {
  131.                 strcpy(found, buf);
  132.                 len = (int)(scan - buf);
  133.                 break;
  134.             }
  135.         }
  136.     }
  137.  
  138.     /* we're through reading */
  139.     fclose(tfile);
  140.  
  141.     /* if there's anything in found[], use it */
  142.     if (found[0])
  143.     {
  144.         return &found[len + 1];
  145.     }
  146.  
  147.     /* else we didn't find it */
  148.     return (char *)0;
  149. }
  150.  
  151. /* This function reads a single textline from a binary file.  It returns
  152.  * the number of bytes read, or 0 at EOF.
  153.  */
  154. int getline(buf, limit, fp)
  155.     char    *buf;    /* buffer to read into */
  156.     int    limit;    /* maximum characters to read */
  157.     FILE    *fp;    /* binary stream to read from */
  158. {
  159.     int    bytes;    /* number of bytes read so far */
  160.     int    ch;    /* single character from file */
  161.  
  162.     for (bytes = 0, ch = 0; ch != '\n' && --limit > 0 && (ch = getc(fp)) != EOF; bytes++)
  163.     {
  164. #if MSDOS || TOS || OS2
  165.         /* since this is a binary file, we'll need to manually strip CR's */
  166.         if (ch == '\r')
  167.         {
  168.             continue;
  169.         }
  170. #endif
  171.         *buf++ = ch;
  172.     }
  173.     *buf = '\0';
  174.  
  175.     return bytes;
  176. }
  177.  
  178.  
  179. /* This function reads a source file, looking for a given tag.  If it finds
  180.  * the tag, then it displays it and returns TRUE.  Otherwise it returns FALSE.
  181.  * To display the tag, it attempts to output any introductory comment, the
  182.  * tag line itself, and any arguments.  Arguments are assumed to immediately
  183.  * follow the tag line, and start with whitespace.  Comments are assumed to
  184.  * start with lines that begin with "/ *", "//", "(*", or "--", and end at the
  185.  * tag line or at a blank line.
  186.  */
  187. int lookup(dir, entry)
  188.     char    *dir;    /* name of the directory that contains the source */
  189.     char    *entry;    /* source filename, <Tab>, linespec */
  190. {
  191.     char    *name;        /* basename of source file */
  192.     char    buf[BLKSIZE];    /* pathname of source file */
  193.     long    lnum;        /* desired line number */
  194.     long    thislnum;    /* current line number */
  195.     long    here;        /* seek position where current line began */
  196.     long    comment;    /* seek position of introductory comment, or -1L */
  197.     FILE    *sfile;        /* used for reading the source file */
  198.     int    len;        /* length of string */
  199.     int    noargs = 0;    /* boolean: don't show lines after tag line? */
  200.     char    *ptr;
  201.  
  202.  
  203.     /* construct the pathname of the source file */
  204.     name = entry;
  205.     strcpy(buf, dir);
  206.     ptr = buf + strlen(buf);
  207. #if AMIGA
  208.     if (ptr[-1] != COLON)
  209. #endif
  210.     *ptr++ = SLASH;
  211.     while (*entry != '\t')
  212.     {
  213.         *ptr++ = *entry++;
  214.     }
  215.     *entry++ = *ptr = '\0';
  216.  
  217.     /* searching for string or number? */
  218.     if (*entry >= '0' && *entry <= '9')
  219.     {
  220.         /* given a specific line number */
  221.         lnum = atol(entry);
  222.         entry = (char *)0;
  223.         noargs = 1;
  224.     }
  225.     else
  226.     {
  227.         /* given a string -- strip off "/^" and "$/\n" */
  228.         entry += 2;
  229.         len = strlen(entry) - 2;
  230.         if (entry[len - 1] == '$')
  231.         {
  232.             entry[len - 1] = '\n';
  233.         }
  234.         if (!strchr(entry, '('))
  235.         {
  236.             noargs = 1;
  237.         }
  238.         lnum = 0L;
  239.     }
  240.  
  241.     /* Open the file.  Note that we open the file in binary mode even
  242.      * though we know it is a text file, because ftell() and fseek()
  243.      * don't work on text files.
  244.      */
  245. #if MSDOS || TOS || OS2
  246.     sfile = fopen(buf, "rb");
  247. #else
  248. # if AMIGA
  249.     if (buf[0] == '.' && buf[1] == SLASH)
  250.         sfile = fopen(&buf[2], "r");
  251.     else
  252. # endif
  253.     sfile = fopen(buf, "r");
  254. #endif
  255.     if (!sfile)
  256.     {
  257.         /* can't open the real source file.  Try "refs" instead */
  258. #if AMIGA
  259.         if (dir[strlen(dir) - 1] == COLON)
  260.             sprintf(buf, "%srefs", dir);
  261.         else
  262. #endif
  263.         sprintf(buf, "%s%crefs", dir, SLASH);
  264. #if MSDOS || TOS || OS2
  265.         sfile = fopen(buf, "rb");
  266. #else
  267. # if AMIGA
  268.         if (buf[0] == '.' && buf[1] == SLASH)
  269.             sfile = fopen(&buf[2], "r");
  270.         else
  271. # endif
  272.         sfile = fopen(buf, "r");
  273. #endif
  274.         if (!sfile)
  275.         {
  276.             /* failed! */
  277.             return 0;
  278.         }
  279.         name = "refs";
  280.     }
  281.  
  282.     /* search the file */
  283.     for (comment = -1L, thislnum = 0; here = ftell(sfile), thislnum++, getline(buf, BLKSIZE, sfile) > 0; )
  284.     {
  285.         /* Is this the start/end of a comment? */
  286.         if (comment == -1L)
  287.         {
  288.             /* starting a comment? */
  289.             if (buf[0] == '/' && buf[1] == '*'
  290.              || buf[0] == '/' && buf[1] == '/'
  291.              || buf[0] == '(' && buf[1] == '*'
  292.              || buf[0] == '-' && buf[1] == '-')
  293.             {
  294.                 comment = here;
  295.             }
  296.         }
  297.         else
  298.         {
  299.             /* ending a comment? */
  300.             if (buf[0] == '\n' || buf[0] == '#')
  301.             {
  302.                 comment = -1L;
  303.             }
  304.         }
  305.  
  306.         /* is this the tag line? */
  307.         if (lnum == thislnum || (entry && !strncmp(buf, entry, len)))
  308.         {
  309.             /* display the filename & line number where found */
  310.             if (strcmp(dir, "."))
  311.                 printf("%s%c%s, line %ld:\n", dir, SLASH, name, thislnum);
  312.             else
  313.                 printf("%s, line %ld:\n", name, thislnum);
  314.  
  315.             /* if there were introductory comments, show them */
  316.             if (comment != -1L)
  317.             {
  318.                 fseek(sfile, comment, 0);
  319.                 while (comment != here)
  320.                 {
  321.                     getline(buf, B